import Taro from '@tarojs/taro'

import { IVolunteerInfo } from '@/models'
import { ICommunicationLetterInfo } from '@/models/communication'
import { stringRandom } from '@/utils/funtions'

import {
    IApply2Resp,
    IApplyReq,
    ICommunicationInfoRes,
    ICommunicationLetterReq,
    ICommunicationReq,
    IUniversityReq,
    IUniversityRes,
    IUploadOssReq,
    IUploadOssRes,
    IUploadReq,
    IUploadRes,
    IWriteLetterReq,
    IWriteLetterRes,
} from './type'
import { IApplyInfo } from '@/models/apply'

export default class LxfService<T> {
    private request: any = () => {
        throw new Error('PromoterDataService.request is undefined');
    };
    private baseURL: string | ((path: string) => string) = '';
    sid: string = '';

    constructor(options?: {
        baseURL?: string | ((path: string) => string);
        request?<R>(
            params: {
                url: string;
                method: 'GET' | 'DELETE' | 'POST' | 'PUT' | 'PATCH';
                data?: any;
                params?: any;
                headers?: any;
            },
            options?: T
        ): Promise<R>;
    }) {
        this.request = options?.request || this.request;
        this.baseURL = options?.baseURL || '';
    }

    private genBaseURL(path: string) {
        return typeof this.baseURL === 'string' ? this.baseURL + path : this.baseURL(path);
    }

    /**
     * GET /University
     *
     * 获取学校列表
     */
    getUniversity(req?: IUniversityReq, options?: T): Promise<IUniversityRes> {
        const url = this.genBaseURL('/University');
        const method = 'GET';
        return this.request({ url, method, data: req }, options);
    }

    getAuth(req?: any, options?: T): Promise<any> {
        const url = this.genBaseURL('/Auth');
        const method = 'POST';
        return this.request({ url, method, data: req }, options);
    }

    getVolunteer(req?: any, options?: T): Promise<IVolunteerInfo> {
        const url = this.genBaseURL('/Volunteer');
        const method = 'GET';
        return this.request({ url, method, data: req }, options);
    }
    getCommunicationInfo(req?: ICommunicationReq, options?: T): Promise<ICommunicationInfoRes> {
        const url = this.genBaseURL('/Communication');
        const method = 'GET';
        return this.request({ url, method, data: req }, options);
    }
    getCommunicationLetter(req?: ICommunicationLetterReq, options?: T): Promise<ICommunicationLetterInfo> {
        const url = this.genBaseURL('/CommunicationLetter');
        const method = 'GET';
        return this.request({ url, method, data: req }, options);
    }

    upload(req?: IUploadReq, options?: T): Promise<IUploadRes> {
        const url = this.genBaseURL('/Upload');
        const method = 'GET';
        return this.request({ url, method, data: req }, options);
    }

    async uploadOss(req?: IUploadOssReq): Promise<IUploadOssRes> {
        const filename = `${stringRandom(5)}${Number(new Date())}.png`;
        const res = await this.upload({ type: 'image', title: filename });
        let extraHeaders;
        try {
            extraHeaders = JSON.parse(res.oss_meta);
        } catch (error) {
            extraHeaders = {};
        }
        const formData = {
            name: filename,
            key: `${res.dir}.png`,
            policy: res.policy,
            OSSAccessKeyId: res.accessid,
            success_action_status: 200,
            callback: res.callback,
            signature: res.signature,
            'x:upload_type': 'image',
            'x:title': filename,
            ...extraHeaders
        };
        const uploadRes: IUploadOssRes = await new Promise((resolve, reject) => {
            Taro.uploadFile({
                url: res.host,
                filePath: req?.file || '',
                name: "file",
                formData,
                success: (res: any) => {
                    try {
                        const data = JSON.parse(res.data) as IUploadOssRes;
                        resolve(data);
                    } catch (error) {
                        reject(error)
                    }

                },
                fail: (res) => {
                    reject(res)
                }
            })
        });
        return uploadRes;
    }

    writeLetter(req?: IWriteLetterReq, options?: T): Promise<IWriteLetterRes> {
        const url = this.genBaseURL('/CommunicationLetter');
        const method = 'POST';
        return this.request({ url, method, data: req }, options);
    }

    updateMobileNumber(req?: { phoneNumber?: string }, options?: T): Promise<IVolunteerInfo> {
        const url = this.genBaseURL('/VolunteerInfo');
        const method = 'POST';
        return this.request({ url, method, data: req }, options);
    }

    createVolunteer(req?: IVolunteerInfo, options?: T): Promise<{ status: number, info: string }> {
        const url = this.genBaseURL('/VolunteerInfo');
        const method = 'PUT';
        return this.request({ url, method, data: req }, options);
    }

    updateVolunteerInfo(req?: IVolunteerInfo, options?: T): Promise<{ status: number, info: string }> {
        const url = this.genBaseURL('/VolunteerInfo');
        const method = 'POST';
        return this.request({ url, method, data: req }, options);
    }

    getVolunteerApplyStep1Questions(req?: any, options?: T): Promise<IApplyInfo> {
        const url = this.genBaseURL('/VolunteerApplyStep1');
        const method = 'GET';
        return this.request({ url, method, data: req }, options);
    }
    postVolunteerApplyStep1Answer(req?: IVolunteerInfo, options?: T): Promise<{ status: number, info: string }> {
        const url = this.genBaseURL('/VolunteerApplyStep1');
        const method = 'POST';
        return this.request({ url, method, data: req }, options);
    }

    getVolunteerApplyStep2Questions(req?: any, options?: T): Promise<IApplyInfo> {
        const url = this.genBaseURL('/VolunteerApplyStep2');
        const method = 'GET';
        return this.request({ url, method, data: req }, options);
    }
    postVolunteerApplyStep2Answer(req?: IApplyReq, options?: T): Promise<IApply2Resp> {
        const url = this.genBaseURL('/VolunteerApplyStep2');
        const method = 'POST';
        return this.request({ url, method, data: req }, options);
    }

    getVolunteerApplyStep3Questions(req?: any, options?: T): Promise<IApplyInfo> {
        const url = this.genBaseURL('/VolunteerApplyStep3');
        const method = 'GET';
        return this.request({ url, method, data: req }, options);
    }
    postVolunteerApplyStep3Answer(req?: IApplyReq, options?: T): Promise<IApply2Resp> {
        const url = this.genBaseURL('/VolunteerApplyStep3');
        const method = 'POST';
        return this.request({ url, method, data: req }, options);
    }

}